<?php
//$conn = DB::instance(array('dbname'=>'default'));
class MysqlDB{
    /*
     * Author 吴啸
     * Create 2011-7-1
     * Description 数据库类
     *
     * Methods
     * ::config(array $config)
     *
     * ->select_db(string $dbname)
     * ->set_charset(string $charset)
     *
     * ->query(string $sql,boolean $to_array = true,int $result_type = MYSQL_ASSOC)
     * ->fetch_array(resource $result,int $result_type = MYSQL_BOTH)
     *
     * ->num_rows(mixed $request)
     * ->insert_id()
     *
     * ->last_sqls(int $num = 1)
     * ->error(int $num = 1)
     * ->last_errors(int $num = 1)
     * ->last_query()
     *
     * Example
     * $conndb = DB::instance();
     * 或者
     * $conndb = DB::instance(array(
     *     'host' => 'localhost',
     *     'dbname' => 'default',
     *     'username' => 'root',
     *     'password' => '',
     *     'charset' => 'utf8'
     * ));
     *
     * */
    
    private static $_config = array(
    //主机地址
        'host' => 'localhost',
    //数据库名
        'dbname' => 'default',
    //用户名
        'username' => 'root',
    //密码
        'password' => '',
    //字符集
        'charset' => 'utf8'
    );
    
    //是否保存查询错误信息
    private $_save_errors = 1;
    
    //查询错误信息寄存条目上限
    private $_errors_amount = 5;
    
    //查询错误信息寄存器
    private $_errors = array();
    
    //查询语句寄存条目上限
    private $_ok_sqls_amount = 5;
    
    //查询语句寄存器
    private $_ok_sqls = array();
    
    //最近一条查询语句
    private $_last_sql;
    
    //类实体寄存器
    private static $_instance;
    
    //数据库实体寄存器
    private $_conn;
    
    function __construct(){
        //根据给定参数建立数据库连接
        $this->_conn = mysql_connect(
            self::$_config['host'],
            self::$_config['username'],
            self::$_config['password'],
            true
        );
    }
    
	public static function get_instance(){
    	return self::$_instance;
    }
    
    public static function instance(array $arr_config = array()){
        if (count(array_filter($arr_config))){
            self::config($arr_config);
        }
        if ( 0 < func_num_args() && false != ( $arr_config = func_get_arg(0)) ){
            self::config($arr_config);
        }
        //数据库对象实例化
        self::$_instance = new self;
        if (!self::$_instance->select_db(self::$_config['dbname'])){
            echo 'select conndb:',self::$_config['dbname'],' error.';
        }
        self::$_instance->set_charset(self::$_config['charset']);
        return self::$_instance;
    }
    
    //传递设置参数
    public static function config(array $arr_config){
        if ( 0 != count( $intersect = array_intersect_key( $arr_config,self::$_config ) ) ){
            self::$_config = array_merge(self::$_config,$intersect);
        }
    }
    
    //数据库选择
    public function select_db($str_db){
        return mysql_select_db($str_db,$this->_conn);
    }
    
    //设定字符集
    public function set_charset($str_charset){
        return mysql_set_charset($str_charset,$this->_conn);
    }
    
    /*
     * 数据库查询
     * @param        sql string        待查询的SQL语句
     * @param        to_array bool    是否将结果集转换成数组后再返回
     * @parame        result_type int    返回的结果集类型，同mysql_fetch_array的结果集类型参数
     * @return mysql结果集/或者/结果集转换成的数组
     * @exception return false
     * */
    public function query($sql,$result_type = MYSQL_BOTH,$to_array = true){
        return $this->sqlInspecte($sql,$result_type,$to_array,1);
    }
    
    //无缓存查询
    public function unbuffered_query($sql,$result_type = MYSQL_BOTH,$to_array = true){
        return $this->sqlInspecte($sql,$result_type,$to_array,0);
    }
    
    //sql分句隔断
    private function sqlInspecte($sql,$result_type,$to_array,$query_method){
        $sqls = trim($sql,';');
        //分句隔断点正则表达
        $preg = '/;(?=insert|delete|update|select|alter)/i';
        if (!preg_match($preg,$sqls)){
            return $this->querySql($sqls,$result_type,$to_array,$query_method);
        }else{
            $sqls = preg_split($preg,$sqls);
            foreach ($sqls as $sqls_v){
                $result = $this->querySql($sqls_v,$result_type,$to_array,$query_method);
                if ((false === $result) || is_array($result) || is_resource($result)){
                    return $result;
                }
            }
            return true;
        }
    }
    
    //主查询方法
    private function querySql($sql,$result_type = MYSQL_BOTH,$to_array = true,$query_method = 1){
        //存储最近一条查询语句
        self::$_instance->_last_sql = $sql;
        
        if ($query_method){
            $result = mysql_query($sql,$this->_conn);
        }else{
            $result = mysql_unbuffered_query($sql,$this->_conn);
        }
        
        //query succeed
        if (false != $result){
            //存储最近一条成功的查询语句
            array_unshift(self::$_instance->_ok_sqls,$sql);
            if (self::$_instance->_ok_sqls_amount < count(self::$_instance->_ok_sqls)){
                array_pop(self::$_instance->_ok_sqls);
            }
            
            //返回查询结果集
            return (!is_resource($result) || !$to_array)?$result:self::$_instance->fetch_array($result,$result_type);
        }
        
        //query failed
        if (self::$_instance->_save_errors){
            //存储最近一条查询失败的错误信息
            array_unshift(self::$_instance->_errors,$sql."::ERROR::".mysql_error());
            if (self::$_instance->_errors_amount < count(self::$_instance->_errors)){
                array_pop(self::$_instance->_errors);
            }
        }
        
        return false;
    }
    
    //获得最后一条查询语句
    public function last_query(){
        return self::$_instance->_last_sql;
    }
    
    //结果集转成数组
    public function fetch_array($result,$result_type = MYSQL_BOTH){
        $array = array();
        while ($temp = mysql_fetch_array($result,$result_type)){
            $array[] = $temp;
        }
        
        return $array;
    }
    
    //获取结果集行数
    public function num_rows($request){
        //如果是结果集
        if (is_resource($request)){
            return mysql_num_rows($request);
        }
        //如果是查询语句字符串
        if (is_string($request)){
            return mysql_num_rows(self::$_instance->query($request,MYSQL_NUM,false));
        }
        //如果是结果集转换后的数组
        if (is_array($request)){
            return count($request);
        }
        
        return false;
    }
    
    //获取最近的成功的查询语句，参数$num为从1到保存上限的integer
    public function last_ok_sql($num = 1){
        if (--$num <= self::$_instance->_ok_sqls_amount){
            return !empty(self::$_instance->_ok_sqls[$num])?self::$_instance->_ok_sqls[$num]:'尚未有成功的查询';
        }else{
            return '错误的下标';
        }
    }
    
    //获取所有最近的成功的查询语句,return array
    public function last_ok_sqls(){
        if (!empty(self::$_instance->_ok_sqls)){
            return self::$_instance->_ok_sqls;
        }else{
            return '尚未有成功的查询';
        }
    }
    
    //获取最近的查询失败信息，参数$num为从1到保存上限的integer
    public function error($num = 1){
        if (--$num <= self::$_instance->_errors_amount){
            return !empty(self::$_instance->_errors[$num])?self::$_instance->_errors[$num]:'暂无错误信息';
        }else{
            return '错误的下标';
        }
    }
    
    //获取所有最近的查询失败信息
    public function last_errors(){
        if (!empty(self::$_instance->_errors)){
            return self::$_instance->_errors;
        }else{
            return '暂无错误信息';
        }
    }
    
    //获取最后插入的行的id
    public function insert_id(){
        return mysql_insert_id($this->_conn);
    }
    
    public function close(){
        self::$_instance = '';
    }
    
    function __destruct(){
        if (is_resource($this->_conn)){
            mysql_close($this->_conn);
        }
    }
}  